package net.translate
{
	import flash.utils.ByteArray;
	
	import utils.StringUtil;
	import utils.pool.ObjectPool;
	
	public class MessageTranslater
	{
		public function MessageTranslater()
		{
		}
		/**
		 * 对数据进行加密，转换为可以发送的字节数组
		 * @param name 对象的名称
		 * @param data 要进行加密的对象
		 * @return 加密完成的字节数组
		 */		
		public static function encode(name:String, data:Object):ByteArray {
			var bytes:ByteArray = new ByteArray();
			var tempBytes:ByteArray;
			var nameLen:int = StringUtil.length(name);
			if(data == null) return bytes;
			if(data is Boolean) {
				// 布尔值
				bytes.writeInt(7 + nameLen + 1);
				bytes.writeByte(DataType.BOOLEAN);
				bytes.writeUTF(name);
				bytes.writeBoolean(data);
			} else if(data is int) {
				// 整数
				bytes.writeInt(7 + nameLen + 4);
				bytes.writeByte(DataType.INT);
				bytes.writeUTF(name);
				bytes.writeInt(int(data));
			} else if(data is Number) {
				// 小数
				bytes.writeInt(7 + nameLen + 8);
				bytes.writeByte(DataType.DOUBLE);
				bytes.writeUTF(name);
				bytes.writeDouble(Number(data));
			} else if(data is String) {
				// 字符串
				tempBytes = ObjectPool.pop(ByteArray);
				tempBytes.length = 0;
				tempBytes.position = 0;
				tempBytes.writeUTFBytes(String(data));
				bytes.writeInt(7 + nameLen + tempBytes.length);
				bytes.writeByte(DataType.STRING);
				bytes.writeUTF(name);
				bytes.writeBytes(tempBytes, 0, tempBytes.length);
				ObjectPool.push(tempBytes);
			} else if(data is ByteArray) {
				// 字节数组
				tempBytes = ByteArray(data);
				bytes.writeInt(7 + nameLen + tempBytes.length);
				bytes.writeByte(DataType.BYTE_ARRAY);
				bytes.writeUTF(name);
				bytes.writeBytes(tempBytes, 0, tempBytes.length);
			} else if(data is Array) {
				// 数组
				var arr:Array = data as Array;
				tempBytes = ObjectPool.pop(ByteArray);
				tempBytes.length = 0;
				tempBytes.position = 0;
				for(var i:int = 0; i < arr.length; i++) {
					var obj:Object = arr[i];
					var t:ByteArray = encode(i.toString(), obj);
					tempBytes.writeBytes(t, 0, t.length);
				}
				bytes.writeInt(7 + nameLen + tempBytes.length);
				bytes.writeByte(DataType.ARRAY);
				bytes.writeUTF(name);
				bytes.writeBytes(tempBytes, 0, tempBytes.length);
				ObjectPool.push(tempBytes);
			} else if(data is Object) {
				// Object，需要递归解析
				tempBytes = ObjectPool.pop(ByteArray);
				tempBytes.length = 0;
				tempBytes.position = 0;
				for(var str:String in data) {
					obj = data[str];
					t = encode(str, obj);
					tempBytes.writeBytes(t, 0, t.length);
				}
				bytes.writeInt(7 + nameLen + tempBytes.length);
				bytes.writeByte(DataType.OBJECT);
				bytes.writeUTF(name);
				bytes.writeBytes(tempBytes, 0, tempBytes.length);
				ObjectPool.push(tempBytes);
			}
			// 将流指针移动回原点
			bytes.position = 0;
			return bytes;
		}
		/**
		 * 对字节数组进行解密，成为一个Object
		 * @param bytes 要进行解密的字节数组
		 * @return 解密完成的对象Object
		 */		
		public static function decode(bytes:ByteArray):TranslateVO {
			bytes.position = 0;
			var value:TranslateVO = new TranslateVO();
			value.length = bytes.readInt();
			value.type = bytes.readByte();
			value.name = bytes.readUTF();
			var nameLen:int = StringUtil.length(value.name);
			var tempBytes:ByteArray;
			switch(value.type) {
				case DataType.BOOLEAN:
					value.data = bytes.readBoolean();
					break;
				case DataType.BYTE:
					value.data = bytes.readByte();
					break;
				case DataType.SHORT:
					value.data = bytes.readShort();
					break;
				case DataType.INT:
					value.data = bytes.readInt();
					break;
				case DataType.FLOAT:
					value.data = bytes.readFloat();
					break;
				case DataType.DOUBLE:
					value.data = bytes.readDouble();
					break;
				case DataType.STRING:
					tempBytes = ObjectPool.pop(ByteArray);
					tempBytes.length = 0;
					tempBytes.position = 0;
					bytes.readBytes(tempBytes, 0, value.length - 7 - nameLen);
					value.data = tempBytes.toString();
					ObjectPool.push(tempBytes);
					break;
				case DataType.BYTE_ARRAY:
					value.data = new ByteArray();
					bytes.readBytes(ByteArray(value.data), 0, value.length - 7 - nameLen);
					break;
				case DataType.ARRAY:
					var arr:Array = []
					value.data = arr;
					var len:int = value.length - 7 - nameLen;
					tempBytes = ObjectPool.pop(ByteArray);
					tempBytes.length = 0;
					tempBytes.position = 0;
					bytes.readBytes(tempBytes, 0, len);
					var childBytes:ByteArray = ObjectPool.pop(ByteArray);
					var bytesReaded:int = 0;
					while(bytesReaded < len) {
						var childLen:int = tempBytes.readInt();
						tempBytes.position = bytesReaded;
						childBytes.length = 0;
						childBytes.position = 0;
						tempBytes.readBytes(childBytes, 0, childLen);
						var tempValue:TranslateVO = decode(childBytes);
						arr.push(tempValue.data);
						bytesReaded += childLen;
					}
					ObjectPool.push(childBytes);
					ObjectPool.push(tempBytes);
					break;
				case DataType.OBJECT:
					value.data = {};
					len = value.length - 7 - nameLen;
					tempBytes = ObjectPool.pop(ByteArray);
					tempBytes.length = 0;
					tempBytes.position = 0;
					bytes.readBytes(tempBytes, 0, len);
					childBytes = ObjectPool.pop(ByteArray);
					bytesReaded = 0;
					while(bytesReaded < len) {
						childLen = tempBytes.readInt();
						tempBytes.position = bytesReaded;
						childBytes.length = 0;
						childBytes.position = 0;
						tempBytes.readBytes(childBytes, 0, childLen);
						tempValue = decode(childBytes);
						value.data[tempValue.name] = tempValue.data;
						bytesReaded += childLen;
					}
					ObjectPool.push(childBytes);
					ObjectPool.push(tempBytes);
					break;
			}
			return value;
		}
	}
}